package com.meida.module.admin.provider.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.meida.common.constants.CommonConstants;
import com.meida.common.exception.OpenAlertException;
import com.meida.common.mybatis.base.service.impl.BaseServiceImpl;
import com.meida.common.mybatis.entity.EntityMap;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.query.CriteriaQuery;
import com.meida.common.mybatis.query.CriteriaUpdate;
import com.meida.common.security.http.OpenRestTemplate;
import com.meida.common.utils.FlymeUtils;
import com.meida.module.admin.client.constants.BaseConstants;
import com.meida.module.admin.client.constants.ResourceType;
import com.meida.module.admin.client.entity.BaseApi;
import com.meida.module.admin.provider.mapper.BaseApiMapper;
import com.meida.module.admin.provider.service.BaseApiService;
import com.meida.module.admin.provider.service.BaseAuthorityService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * @author zyf
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class BaseApiServiceImpl extends BaseServiceImpl<BaseApiMapper, BaseApi> implements BaseApiService {
    @Autowired
    private BaseApiMapper baseApiMapper;
    @Autowired
    private BaseAuthorityService baseAuthorityService;
    @Autowired
    private OpenRestTemplate openRestTemplate;

    /**
     * 分页查询
     *
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<BaseApi> cq, BaseApi baseApi, EntityMap requestMap) {
        if (FlymeUtils.isNotEmpty(baseApi)) {
            cq.lambda()
                    .likeRight(FlymeUtils.isNotEmpty(baseApi.getPath()), BaseApi::getPath, baseApi.getPath())
                    .likeRight(FlymeUtils.isNotEmpty(baseApi.getApiName()), BaseApi::getApiName, baseApi.getApiName())
                    .likeRight(FlymeUtils.isNotEmpty(baseApi.getApiCode()), BaseApi::getApiCode, baseApi.getApiCode())
                    .eq(FlymeUtils.isNotEmpty(baseApi.getServiceId()), BaseApi::getServiceId, baseApi.getServiceId())
                    .eq(FlymeUtils.isNotEmpty(baseApi.getStatus()), BaseApi::getStatus, baseApi.getStatus())
                    .eq(FlymeUtils.isNotEmpty(baseApi.getIsAuth()), BaseApi::getIsAuth, baseApi.getIsAuth());
        }
        return ResultBody.ok();
    }

    /**
     * 查询列表
     *
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<BaseApi> findAllList(String serviceId) {
        QueryWrapper<BaseApi> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(FlymeUtils.isNotEmpty(serviceId), BaseApi::getServiceId, serviceId);
        List<BaseApi> list = baseApiMapper.selectList(queryWrapper);
        return list;
    }

    /**
     * 根据主键获取接口
     *
     * @param apiId
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public BaseApi getApi(Long apiId) {
        return baseApiMapper.selectById(apiId);
    }


    /**
     * 检查接口编码是否存在
     *
     * @param apiCode
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public Boolean isExist(String apiCode) {
        QueryWrapper<BaseApi> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(BaseApi::getApiCode, apiCode);
        int count = getCount(queryWrapper);
        return count > 0 ? true : false;
    }

    /**
     * 添加接口
     *
     * @param api
     * @return
     */
    @Override
    public void addApi(BaseApi api) {
        if (isExist(api.getApiCode())) {
            throw new OpenAlertException(String.format("%s编码已存在!", api.getApiCode()));
        }
        if (api.getPriority() == null) {
            api.setPriority(0);
        }
        if (api.getStatus() == null) {
            api.setStatus(BaseConstants.ENABLED);
        }
        if (api.getApiCategory() == null) {
            api.setApiCategory(BaseConstants.DEFAULT_API_CATEGORY);
        }
        if (api.getIsPersist() == null) {
            api.setIsPersist(0);
        }

        if (api.getIsAuth() == null) {
            api.setIsAuth(0);
        }
        baseApiMapper.insert(api);
        // 同步权限表里的信息
        baseAuthorityService.saveOrUpdateAuthority(api.getApiId(), ResourceType.api);
    }

    /**
     * 修改接口
     *
     * @param api
     * @return
     */
    @Override
    public void updateApi(BaseApi api) {
        BaseApi saved = getApi(api.getApiId());
        if (saved == null) {
            throw new OpenAlertException("信息不存在!");
        }
        if (!saved.getApiCode().equals(api.getApiCode())) {
            // 和原来不一致重新检查唯一性
            if (isExist(api.getApiCode())) {
                throw new OpenAlertException(String.format("%s编码已存在!", api.getApiCode()));
            }
        }
        if (api.getPriority() == null) {
            api.setPriority(0);
        }
        if (api.getApiCategory() == null) {
            api.setApiCategory(BaseConstants.DEFAULT_API_CATEGORY);
        }
        baseApiMapper.updateById(api);
        // 同步权限表里的信息
        baseAuthorityService.saveOrUpdateAuthority(api.getApiId(), ResourceType.api);
    }

    /**
     * 查询接口
     *
     * @param apiCode
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public BaseApi getApi(String apiCode) {
        QueryWrapper<BaseApi> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(BaseApi::getApiCode, apiCode);
        return baseApiMapper.selectOne(queryWrapper);
    }


    /**
     * 移除接口
     *
     * @param apiId
     * @return
     */
    @Override
    public void removeApi(Long apiId) {
        BaseApi api = getApi(apiId);
        if (api != null && api.getIsPersist().equals(BaseConstants.ENABLED)) {
            throw new OpenAlertException(String.format("保留数据,不允许删除"));
        }
        baseAuthorityService.removeAuthority(apiId, ResourceType.api);
        baseApiMapper.deleteById(apiId);
    }


    /**
     * 获取数量
     *
     * @param queryWrapper
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public int getCount(QueryWrapper<BaseApi> queryWrapper) {
        return baseApiMapper.selectCount(queryWrapper);
    }

    /**
     * 根据serviceId、path查询
     *
     * @param serviceId
     * @param path
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<BaseApi> findByServiceIdAndPath(String serviceId, String path) {
        QueryWrapper<BaseApi> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(BaseApi::getServiceId, serviceId);
        queryWrapper.lambda().eq(BaseApi::getPath, path);
        List<BaseApi> list = baseApiMapper.selectList(queryWrapper);
        return list;
    }


    @Override
    public ResultBody afterSetState(CriteriaUpdate cu) {
        // 刷新网关
        openRestTemplate.refreshGateway();
        Long apiId = cu.getLong("apiId");
        BaseApi api = getById(apiId);
        if (FlymeUtils.isNotEmpty(api)) {
            String notAuthKey = CommonConstants.NOTAUTH_KEY + api.getServiceId();
            Map<Object, Object> list = redisUtils.getMap(notAuthKey);
            if (FlymeUtils.isEmpty(list)) {
                list = new HashedMap();
            }
            Object path = list.get(api.getApiCode());
            if (api.getIsAuth().equals(CommonConstants.DISABLED)) {
                list.put(api.getApiCode(), api.getPath());
            }
            if (FlymeUtils.isNotEmpty(path) && api.getIsAuth().equals(CommonConstants.ENABLED)) {
                list.remove(api.getApiCode());
            }
            redisUtils.del(notAuthKey);
            redisUtils.setMap(notAuthKey, list);
        }
        return ResultBody.msg("设置成功");
    }
}
